package snafu.framework.agents;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import snafu.framework.actions.AbstractAction;
import snafu.framework.actions.Intention;
import snafu.framework.actions.IntentionItself;
import snafu.framework.exceptions.SnafuException;
import snafu.framework.senses.Sense;
import snafu.framework.senses.SenseItself;
import snafu.framework.states.StateView;
import snafu.framework.view.Access;

public class AgentStateView extends StateView implements AgentState {

	/**
	 * Initiates a new view of the given AgentState with the given access type.
	 * 
	 * @param access
	 *            the access type
	 * @param state
	 *            the original agent state
	 */
	public AgentStateView(Access access, AgentStateItself state) {
		super(access, state);
	}

	/**
	 * Creates a list of views from the original state where the access type is lower or equal to
	 * this access type.
	 */
	@Override
	public List<Intention<? extends AbstractAction>> getIntentions() {
		List<Intention<?>> intentionViews = new ArrayList<Intention<?>>();
		for (IntentionItself<? extends AbstractAction> intention : ((AgentStateItself) state).intentions) {
			
			if (intention.getPrivacy().ordinal() <= access.ordinal()) {
				intentionViews.add(intention.createView(access));
			}
		}
		return intentionViews;
	}

	/**
	 * Returns a copy of the intentions found. Null if no intentions was found, exception if more
	 * than one was found.
	 */
	@SuppressWarnings("unchecked")
	@Override
	public <I extends Intention<?>> I getIntention(Class<I> clazz) {
		// select intentions matching clazz
		List<Intention<?>> selectedIntentions = new ArrayList<Intention<?>>();
		for (Intention<?> intention : getIntentions()) {
			if (clazz.isAssignableFrom(intention.getClass())) {
				selectedIntentions.add(intention);
			}
		}

		// check how many matches were found
		switch (selectedIntentions.size()) {
		case 0:
			return null;
		case 1:
			return (I) selectedIntentions.get(0);
		default:
			throw new SnafuException("found more than one matching intention for " + clazz);
		}
	}
	
	@Override
	public Set<Sense> getSenses() {
		Set<Sense> copiedSenses = new HashSet<Sense>();
		for (SenseItself sense : ((AgentStateItself) state).senses) {
			copiedSenses.add(sense.createView(access));
		}
		
		return copiedSenses;
	}

}
